package br.net.woodstock.tickettoride.client.ws.jee;

import java.util.Date;

import javax.crypto.SecretKey;

import br.net.woodstock.tickettoride.client.TicketData;
import br.net.woodstock.tickettoride.client.TicketException;
import br.net.woodstock.tickettoride.client.TicketHash;
import br.net.woodstock.tickettoride.client.TicketRequest;
import br.net.woodstock.tickettoride.client.TicketSession;
import br.net.woodstock.tickettoride.client.common.DefaultTicketData;
import br.net.woodstock.tickettoride.client.common.DefaultTicketHash;
import br.net.woodstock.tickettoride.client.config.TicketConfig;
import br.net.woodstock.tickettoride.client.utils.CodecUtils;
import br.net.woodstock.tickettoride.client.utils.KeyUtils;
import br.net.woodstock.tickettoride.client.utils.StringUtils;
import br.net.woodstock.tickettoride.client.ws.jee.internal.TicketID;
import br.net.woodstock.tickettoride.client.ws.jee.internal.TicketServiceWS;

class TicketSessionImpl implements TicketSession {

	private TicketServiceWS	ws;

	private String			session;

	private SecretKey		secretKey;

	public TicketSessionImpl(final TicketServiceWS ws, final String session, final byte[] key) {
		super();
		try {
			this.ws = ws;
			this.session = session;

			byte[] encodedKey = CodecUtils.fromBase64(key);
			byte[] decodedKey = CodecUtils.decrypt(TicketConfig.getInstance().getPKCS12().getPrivateKey(), encodedKey);

			this.secretKey = KeyUtils.loadSecretKey(decodedKey);
		} catch (Exception e) {
			throw new TicketException(e);
		}
	}

	@Override
	public TicketHash send(final TicketRequest request) {
		try {
			byte[] encrypted = CodecUtils.encrypt(this.secretKey, request.getData());
			byte[] sha1 = CodecUtils.getSHA1(encrypted);
			byte[] encryptedSha1 = CodecUtils.encrypt(TicketConfig.getInstance().getPKCS12().getPrivateKey(), sha1);
			byte[] base64 = CodecUtils.toBase64(encrypted);
			byte[] base64Sha1 = CodecUtils.toBase64(encryptedSha1);

			br.net.woodstock.tickettoride.client.ws.jee.internal.TicketSession ts = new br.net.woodstock.tickettoride.client.ws.jee.internal.TicketSession();
			ts.setHash(this.session);

			br.net.woodstock.tickettoride.client.ws.jee.internal.TicketRequest tr = new br.net.woodstock.tickettoride.client.ws.jee.internal.TicketRequest();
			tr.setData(base64);
			tr.setExpires(request.getExpires());
			tr.setSession(ts);
			tr.setSignature(base64Sha1);
			tr.setToApplication(request.getDestination());

			TicketID id = this.ws.createTicket(tr);
			TicketHash response = new DefaultTicketHash(id.getHash());
			return response;
		} catch (Exception e) {
			throw new TicketException(e);
		}
	}

	@Override
	public TicketData getData(final TicketHash hash) {
		try {
			br.net.woodstock.tickettoride.client.ws.jee.internal.TicketSession ts = new br.net.woodstock.tickettoride.client.ws.jee.internal.TicketSession();
			ts.setHash(this.session);

			TicketID id = new TicketID();
			id.setHash(hash.getHash());

			br.net.woodstock.tickettoride.client.ws.jee.internal.TicketData td = this.ws.getTicketData(ts, id);

			byte[] data = CodecUtils.fromBase64(td.getBytes());
			byte[] signature = CodecUtils.fromBase64(td.getSignature());
			byte[] decryptedData = CodecUtils.decrypt(this.secretKey, data);
			byte[] decryptedSignature = CodecUtils.decrypt(TicketConfig.getInstance().getPKCS12().getPrivateKey(), signature);

			String sha1Data = CodecUtils.getSHA1String(data);
			String sha1Signature = StringUtils.toString(decryptedSignature);

			if (!sha1Data.equalsIgnoreCase(sha1Signature)) {
				throw new TicketException("Signature not match");
			}

			String application = td.getApplication();
			Date date = td.getDate().toGregorianCalendar().getTime();
			Date expires = td.getExpires().toGregorianCalendar().getTime();

			return new DefaultTicketData(application, date, expires, decryptedData);
		} catch (Exception e) {
			throw new TicketException(e);
		}
	}

}
